﻿// ===============================================================================
// XCI.NET 西安交通信息WinForm开发框架 2018 版权所有
// ===============================================================================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using XCI.Core;

namespace XCI.Helper
{
    /// <summary>
    /// 对象帮助类
    /// </summary>
    /// <example>
    /// <code>
    /// /// <summary>
    /// /// 测试类
    /// /// </summary>
    /// public class Person
    /// {
    ///     /// <summary>
    ///     /// 姓名
    ///     /// </summary>
    ///     public string Name { get; set; }
    /// 
    ///     /// <summary>
    ///     /// 测试方法
    ///     /// </summary>
    ///     public void Hello(string name)
    ///     {
    ///         this.Name = name;
    ///         var person =  new Person();
    ///         person.Name = name;
    ///     }
    /// }
    /// </code>
    /// <code> 
    /// using XCI.Helper;
    ///  
    /// Win32Helper.ShowConsole();//显示cmd窗口
    /// 
    /// Type personType = typeof(Person);
    /// MethodInfo methodInfo = personType.GetMethod("Hello");
    /// PropertyInfo propertyInfo = personType.GetProperty("Name");
    /// Person person = new Person();
    /// object nameTemp = null;
    /// const string name = "hello";//参数值
    /// object[] param = new object[] { name };//参数数组
    /// const int times = 500000; //调用次数
    /// </code>
    /// <img src="images/ReflectionHelper.jpg" />
    /// </example>
    public static class ObjectHelper
    {
        private static readonly List<Type> Types = new List<Type>();
        private static readonly object TypeLockObject = new object();
        /// <summary>
        /// 已加载文件列表
        /// </summary>
        private static readonly List<string> LoadedFileList = new List<string>();

        /// <summary>
        /// 数字类型
        /// </summary>
        private static readonly IDictionary<string, bool> NumericTypes;

        /// <summary>
        /// 基础类型
        /// </summary>
        private static readonly IDictionary<string, bool> BasicTypes;

        /// <summary>
        /// 静态构造
        /// </summary>
        static ObjectHelper()
        {
            NumericTypes = new Dictionary<string, bool>
            {
                [nameof(Int32)] = true,
                [nameof(Int64)] = true,
                [nameof(Single)] = true,
                [nameof(Double)] = true,
                [nameof(Decimal)] = true,
                [nameof(SByte)] = true,
                [nameof(Int16)] = true,
                [nameof(Int32)] = true,
                [nameof(Int64)] = true,
                [nameof(Double)] = true,
                [nameof(Decimal)] = true
            };

            BasicTypes = new Dictionary<string, bool>
            {
                [nameof(Int32)] = true,
                [nameof(Int64)] = true,
                [nameof(Single)] = true,
                [nameof(Double)] = true,
                [nameof(Decimal)] = true,
                [nameof(SByte)] = true,
                [nameof(Int16)] = true,
                [nameof(Int32)] = true,
                [nameof(Int64)] = true,
                [nameof(Double)] = true,
                [nameof(Decimal)] = true,
                [nameof(Boolean)] = true,
                [nameof(DateTime)] = true,
                [nameof(String)] = true
            };
        }

        /// <summary>
        /// 测试对象是否是数字类型
        /// </summary>
        /// <param name="val">测试对象</param>
        public static bool IsNumeric(object val)
        {
            return NumericTypes.ContainsKey(val.GetType().Name);
        }

        /// <summary>
        /// 测试类型是否是数字类型
        /// </summary>
        /// <param name="type">测试类型</param>
        public static bool IsNumeric(Type type)
        {
            return NumericTypes.ContainsKey(type.Name);
        }

        /// <summary>
        /// 测试类型是否是布尔类型
        /// </summary>
        /// <param name="type">测试类型</param>
        public static bool IsBoolean(Type type)
        {
            return type == typeof(bool) || type == typeof(bool?);
        }

        /// <summary>
        /// 测试类型是否是日期类型
        /// </summary>
        /// <param name="type">测试类型</param>
        public static bool IsDateTime(Type type)
        {
            return type == typeof(DateTime);
        }

        /// <summary>
        /// 测试类型是否是字符串数组
        /// </summary>
        /// <param name="type">测试类型</param>
        /// <returns></returns>
        public static bool IsArray(Type type)
        {
            return type == typeof(Object[]);
        }

        /// <summary>
        /// 测试类型是否是基础类型
        /// </summary>
        /// <param name="type">测试类型</param>
        public static bool IsBasicType(Type type)
        {
            return BasicTypes.ContainsKey(type.Name);
        }

        /// <summary>
        /// 把对象转为字符串表示形式
        /// </summary>
        /// <param name="obj">对象</param>
        public static string GetObjectString(object obj)
        {
            if (obj == null)
            {
                return string.Empty;
            }
            var convert = TypeDescriptor.GetConverter(obj.GetType());
            return convert.ConvertToString(obj);
        }

        /// <summary>
        /// 将指定文本转换为对象
        /// </summary>
        /// <param name="objString">对象字符串表示形式</param>
        /// <param name="type">对象类型</param>
        public static object GetObjectFromString(string objString, Type type)
        {
            var convert = TypeDescriptor.GetConverter(type);
            return convert.ConvertFromString(objString);
        }

        /// <summary>
        /// 返回具有指定 System.Type 而且其值等效于指定对象的 System.Object
        /// </summary>
        /// <param name="value">对象值</param>
        /// <param name="type">对象类型</param>
        /// <returns>返回具有指定 System.Type 而且其值等效于指定对象的 System.Object</returns>
        public static object ConvertObjectValue(object value, Type type)
        {
            if (value == DBNull.Value || null == value)
                return null;

            if (type.IsGenericType &&
                type.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                var nullableConverter = new NullableConverter(type);

                type = nullableConverter.UnderlyingType;
            }
            if (IsDateTime(type) && string.IsNullOrEmpty(value.ToString()))
            {
                return null;
            }
            if (IsNumeric(type) && string.IsNullOrEmpty(value.ToString()))
            {
                return null;
            }

            if (type.IsEnum)
            {
                return Convert.ChangeType(Enum.Parse(type, value.ToString(), true), type);
            }

            if (type == typeof(int) && value is bool vb)
            {
                return vb ? 1 : 0;
            }

            if (type == typeof(bool))
            {
                if (!string.IsNullOrEmpty(value.ToString()))
                {
                    if (value.ToString().Equals("1"))
                    {
                        return true;
                    }
                    if (value.ToString().Equals("true", StringComparison.CurrentCultureIgnoreCase))
                    {
                        return true;
                    }
                    return false;
                }
                return null;
            }
            //if (value.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
            //{
            //    return (value as Newtonsoft.Json.Linq.JObject)?.ToObject(type);
            //}
            return Convert.ChangeType(value, type);
        }

        public static object GetTypeDefaultValue(Type type)
        {
            if (type == typeof(int))
                return 0;
            if (type == typeof(decimal))
                return 0;
            if (type == typeof(DateTime))
                return DateTime.Now;
            if (type == typeof(bool))
                return false;
            return string.Empty;
        }

        /// <summary>
        /// 把数组转换为逗号分隔的字符串
        /// </summary>
        /// <param name="array">数组</param>
        /// <returns>返回逗号分隔的字符串</returns>
        public static string ConvertArrayToString(Array array)
        {
            StringBuilder sb = new StringBuilder();
            foreach (object item in array)
            {
                sb.Append(item);
                sb.Append(",");
            }
            return sb.ToString().TrimEnd(',');
        }

        /// <summary>
        /// 把逗号分隔的字符串分隔成数组对象
        /// </summary>
        /// <typeparam name="T">数组类型</typeparam>
        /// <param name="str">逗号分隔的字符串</param>
        /// <returns>返回指定类型的数组</returns>
        public static Array ConvertStringToArray<T>(string str)
        {
            string[] sz = str.Split(',');
            List<T> list = new List<T>();
            foreach (string item in sz)
            {
                list.Add((T)ObjectHelper.ConvertObjectValue(item, typeof(T)));
            }
            return list.ToArray();
        }

        /// <summary>
        /// 把逗号分隔的字符串分隔成数组对象
        /// </summary>
        /// <typeparam name="T">数组类型</typeparam>
        /// <param name="str">逗号分隔的字符串</param>
        /// <returns>返回指定类型的数组</returns>
        public static List<T> ConvertStringToList<T>(string str)
        {
            string[] sz = str.Split(',');
            List<T> list = new List<T>();
            foreach (string item in sz)
            {
                list.Add((T)ObjectHelper.ConvertObjectValue(item, typeof(T)));
            }
            return list;
        }

        /// <summary>
        /// 检测此类型是否是可空类型
        /// </summary>
        /// <param name="type">测试的类型</param>
        /// <returns>如果是可空类型 返回true</returns>
        public static bool IsNullableType(Type type)
        {
            if (!type.IsValueType) return true;
            if (!type.UnderlyingSystemType.IsGenericType) return false;
            var def = type.UnderlyingSystemType.GetGenericTypeDefinition();
            if (def != null)
            {
                return def == typeof(Nullable<>);
            }
            return false;
        }

        /// <summary>
        /// 获取对象属性名称/属性值 键值对
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>返回属性名称/属性值字典</returns>
        public static Dictionary<string, object> GetPropertyKeyValuePair(object obj)
        {
            var propertyDic = new Dictionary<string, object>();
            if (obj == null) return propertyDic;
            foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(obj))
            {
                propertyDic.Add(propertyDescriptor.Name, propertyDescriptor.GetValue(obj));
            }
            return propertyDic;
        }

        /// <summary>
        /// 获取对象属性名称数组
        /// </summary>
        /// <param name="obj">对象</param>
        public static string[] GetPropertyNames(object obj)
        {
            if (obj == null) return null;
            List<string> list = new List<string>();
            foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(obj))
            {
                list.Add(propertyDescriptor.Name);
            }
            return list.ToArray();
        }

        /// <summary>
        /// 数组比较
        /// </summary>
        /// <typeparam name="T">数组元素类型</typeparam>
        /// <param name="arr1">数组一</param>
        /// <param name="arr2">数组二</param>
        /// <returns>内容相同返回true,否则返回false。</returns>
        public static bool CompareArray<T>(T[] arr1, T[] arr2)
        {
            var q = from a in arr1 join b in arr2 on a equals b select a;
            bool flag = arr1.Length == arr2.Length && q.Count() == arr1.Length;
            return flag;
        }

        #region 属性

        /// <summary>
        /// 复制属性
        /// </summary>
        /// <param name="source">源对象</param>
        /// <param name="target">目标对象</param>
        public static void CopyProperty(object source, object target)
        {
            if (source == null) throw new ArgumentNullException(nameof(source));
            if (target == null) throw new ArgumentNullException(nameof(target));

            var sourceType = source.GetType();
            var pros = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty |
                                                      BindingFlags.SetProperty);
            foreach (PropertyInfo info in pros)
            {
                string proName = info.Name;
                var sourcePro = sourceType.GetProperty(proName);
                if (sourcePro == null || !info.CanWrite)
                {
                    continue;
                }

                var val = sourcePro.GetValue(source);
                info.SetValue(target, val);
            }
        }

        /// <summary>
        /// 设置属性值,支持嵌套属性
        /// </summary>
        /// <param name="instance">对象实例</param>
        /// <param name="propertyName">属性字符串</param>
        /// <param name="propertyValue">属性值</param>
        public static void SetObjectProperty(object instance, string propertyName, object propertyValue)
        {
            if (instance == null || string.IsNullOrEmpty(propertyName)) return;
            if (instance is DataRow row)
            {
                row[propertyName] = propertyValue;
                return;
            }

            string[] propertys = propertyName.Split('.');
            if (propertys.Length == 0) return;
            if (propertys.Length == 1)
            {
                var propertyInfo = TypeDescriptor.GetProperties(instance).Find(propertyName, false);
                if (propertyInfo == null) return;
                propertyInfo.SetValue(instance, ConvertObjectValue(propertyValue, propertyInfo.PropertyType));
            }
            else
            {
                PropertyDescriptor proDesc = TypeDescriptor.GetProperties(instance).Find(propertys[0], false);
                object tempObject = instance;
                for (int i = 1; i < propertys.Length; i++)
                {
                    if (tempObject == null || proDesc == null) break;
                    tempObject = proDesc.GetValue(tempObject);
                    proDesc = proDesc.GetChildProperties().Find(propertys[i], false);
                }
                if (proDesc != null && tempObject != null)
                {
                    proDesc.SetValue(tempObject, ConvertObjectValue(propertyValue, proDesc.PropertyType));
                }
            }
        }

        /// <summary>
        /// 获取属性对象,支持嵌套属性
        /// </summary>
        /// <param name="instance">对象实例</param>
        /// <param name="propertyName">属性字符串</param>
        public static object GetObjectProperty(object instance, string propertyName)
        {
            if (instance == null || string.IsNullOrEmpty(propertyName)) return null;
            if (instance is DataRow row) return row[propertyName];

            string[] propertys = propertyName.Split('.');
            if (propertys.Length == 0) return null;
            if (propertys.Length == 1)
            {
                var propertyInfo = TypeDescriptor.GetProperties(instance).Find(propertyName, false);
                return propertyInfo?.GetValue(instance);
            }

            object tempObject = instance;
            PropertyDescriptor proDesc = TypeDescriptor.GetProperties(tempObject).Find(propertys[0], false);
            for (int i = 1; i < propertys.Length; i++)
            {
                if (tempObject == null || proDesc == null) break;
                tempObject = proDesc.GetValue(tempObject);
                proDesc = proDesc.GetChildProperties().Find(propertys[i], false);
            }
            if (proDesc != null && tempObject != null)
            {
                return proDesc.GetValue(tempObject);
            }
            return null;
        }

        #endregion

        /// <summary>
        /// 创建对象实例 (使用无参数的构造函数创建)
        /// </summary>
        /// <param name="provider">类型字符串(类,程序集)</param>
        /// <returns>对象实例</returns>
        public static object CreateInstance(string provider)
        {
            if (string.IsNullOrEmpty(provider)) return null;
            Type type = Type.GetType(provider, false);
            if (type == null) return null;

            return CreateInstance(type, null);
        }

        /// <summary>
        /// 创建对象实例 (使用无参数的构造函数创建)
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="provider">类型字符串(类,程序集)</param>
        /// <returns>对象实例</returns>
        public static T CreateInstance<T>(string provider) where T : class
        {
            return (T)CreateInstance(provider);
        }

        /// <summary>
        /// 创建对象实例
        /// </summary>
        /// <param name="type">对象类型</param>
        /// <param name="args">构造参数字典</param>
        /// <returns>对象实例</returns>
        public static object CreateInstance(Type type, Dictionary<string, object> args)
        {
            //NewExpression newExpression = Expression.New(type);
            //Expression<Func<object>> newLambda = Expression.Lambda<Func<object>>(newExpression, null);
            //return newLambda.Compile()();
            return Activator.CreateInstance(type, GetConstructorParams(type, args));
        }

        /// <summary>
        /// 创建对象实例
        /// </summary>
        /// <param name="provider">类型字符串(类,程序集)</param>
        /// <param name="args">构造参数字典</param>
        /// <returns>对象实例</returns>
        public static object CreateInstance(string provider, Dictionary<string, object> args)
        {
            if (string.IsNullOrEmpty(provider)) return null;
            Type type = Type.GetType(provider, false);
            //if (type == null) return null;
            if (type == null)
            {
                var msg = $"无效的实现类字符串:{provider}";
                DebugHelper.CatchLogFile(msg);
                //throw new SystemException(msg);
            }

            return CreateInstance(type, args);
        }

        /// <summary>
        /// 创建对象实例 (使用无参数的构造函数创建)
        /// </summary>
        /// <typeparam name="TResult">对象类型</typeparam>
        /// <remarks>
        /// 如果类没有无参数的构造函数则执行会失败
        /// </remarks>
        /// <returns>对象实例</returns>
        public static TResult CreateInstance<TResult>() where TResult : class
        {
            NewExpression newExpression = Expression.New(typeof(TResult));
            Expression<Func<TResult>> newLambda = Expression.Lambda<Func<TResult>>(
                newExpression, null);
            return newLambda.Compile()();
        }


        /// <summary>
        /// 创建对象实例 (使用无参数的构造函数创建)
        /// </summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="type">对象类型</param>
        public static TResult CreateInstance<TResult>(Type type)
        {
            NewExpression newExpression = Expression.New(type);
            Expression<Func<TResult>> newLambda = Expression.Lambda<Func<TResult>>(
                newExpression, null);
            return newLambda.Compile()();
        }

        /// <summary>
        /// 创建泛型对象实例 (使用无参数的构造函数创建)
        /// </summary>
        /// <param name="provider">类型字符串(类,程序集)</param>
        /// <param name="genericType">泛型类型</param>
        /// <returns>对象实例</returns>
        public static object CreateGenericInstance(string provider, params Type[] genericType)
        {
            if (string.IsNullOrEmpty(provider)) return null;
            Type type = Type.GetType(provider, false);
            return CreateGenericInstance(type, genericType);
        }

        /// <summary>
        /// 创建泛型对象实例 (使用无参数的构造函数创建)
        /// </summary>
        /// <param name="type">对象类型</param>
        /// <param name="genericType">泛型类型</param>
        /// <returns>对象实例</returns>
        public static object CreateGenericInstance(Type type, params Type[] genericType)
        {
            if (type == null) return null;
            return Activator.CreateInstance(type.MakeGenericType(genericType));
        }

        /// <summary>
        /// 获取构造函数参数数组
        /// </summary>
        /// <param name="type">对象类型</param>
        /// <param name="constructorParams">构造函数参数与值字典</param>
        /// <returns>返回构造函数参数数组</returns>
        public static object[] GetConstructorParams(Type type, Dictionary<string, object> constructorParams)
        {
            if (constructorParams == null)
            {
                return new object[0];
            }
            var conArgsNames = constructorParams.Keys.ToArray();
            var conArgsCount = conArgsNames.Length;
            var conParam = new object[conArgsCount];
            var constructors = type.GetConstructors();
            foreach (var constructor in constructors)
            {
                var objConParams = constructor.GetParameters();
                if (objConParams.Length != conArgsCount)
                {
                    continue;
                }
                var cArgsNames = objConParams.Select(p => p.Name).ToArray();
                var isEquals = ObjectHelper.CompareArray(conArgsNames, cArgsNames);
                if (!isEquals)
                {
                    continue;
                }
                for (int i = 0; i < conArgsCount; i++)
                {
                    var p = objConParams[i];
                    conParam[i] = ObjectHelper.ConvertObjectValue(constructorParams[p.Name], p.ParameterType);
                }
                break;
            }
            return conParam;
        }

        /// <summary>
        /// 获取当前应用程序中加载的所有类型
        /// </summary>
        public static IEnumerable<Type> GetApplicateTypes()
        {
            lock (TypeLockObject)
            {
                if (Types.Count == 0)
                {
                    var files = IOHelper.GetFiles(IOHelper.RootDirectory);
                    var names = new List<string>();
                    foreach (string item in files)
                    {
                        var name = Path.GetFileName(item);
                        if (names.IndexOf(name) > -1)
                        {
                            continue;
                        }
                        if (!ValidateFileExtension(item)) continue;
                        string assemblyName = Path.GetFileNameWithoutExtension(item);
                        if (string.IsNullOrEmpty(assemblyName)) continue;
                        try
                        {
                            Types.AddRange(Assembly.Load(assemblyName).GetTypes());
                            names.Add(name);
                        }
                        catch (Exception e)
                        {
                            DebugHelper.DebugConsole(e.Message);
                        }
                    }
                }
                return Types;
            }
        }

        /// <summary>
        /// 从当前应用程序中的所有类型中检索继承自指定类型或者实现了指定类型的类型列表。
        /// </summary>
        /// <param name="loadedTypes">已经加载的类型</param>
        /// <param name="subtypes">指定的接口或者父类</param>
        /// <returns>返回当前应用程序中的所有类型中检索继承自指定类型或者实现了指定类型的类型列表。</returns>
        public static IEnumerable<Type> GetSubClassList(IEnumerable<Type> loadedTypes, Type[] subtypes)
        {
            if (subtypes == null || subtypes.Length == 0) return null;
            List<Type> list = new List<Type>();
            foreach (var t in loadedTypes)
            {
                if (ValidInterfaceClass(t, false, subtypes))
                {
                    list.Add(t);
                }
                if (CheckSubClass(t, subtypes))
                {
                    list.Add(t);
                }
            }
            return list;
        }

        /// <summary>
        /// 获取程序集中继承了指定类型的类或者接口(搜索一层继承)
        /// </summary>
        /// <param name="assembly">程序集对象</param>
        /// <param name="baseType">基类型</param>
        /// <returns>返回继承了指定类型的类或接口</returns>
        public static Type[] GetSubClassOrInterface(Assembly assembly, Type baseType)
        {
            return GetSubClassOrInterface(assembly.GetTypes(), baseType);
        }

        /// <summary>
        /// 获取程序集中继承了指定类型的类或者接口(搜索一层继承)
        /// </summary>
        /// <param name="assemblyPath">程序集名称</param>
        /// <param name="baseType">基类型</param>
        /// <returns>返回继承了指定类型的类或接口</returns>
        public static Type[] GetSubClassOrInterface(string assemblyPath, Type baseType)
        {
            Assembly assembly = Assembly.Load(assemblyPath);
            return GetSubClassOrInterface(assembly, baseType);
        }

        /// <summary>
        /// 获取程序集中继承了指定类型的类或者接口(搜索一层继承)
        /// </summary>
        /// <param name="types">类型集合</param>
        /// <param name="baseType">基类型</param>
        /// <returns>返回继承了指定类型的类或接口</returns>
        public static Type[] GetSubClassOrInterface(IEnumerable<Type> types, Type baseType)
        {
            return types.Where(typeItem => typeItem.BaseType == baseType).ToArray();
        }

        /// <summary>
        /// 获取程序集中继承了指定接口的接口
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <param name="interfaces">接口类型</param>
        /// <returns>返回继承了指定接口的接口</returns>
        public static Type[] GetSubInterface(Assembly assembly, params Type[] interfaces)
        {
            return GetSubInterface(assembly.GetTypes(), interfaces);
        }

        /// <summary>
        /// 获取程序集中继承了指定接口的接口
        /// </summary>
        /// <param name="assemblyPath">程序集路径</param>
        /// <param name="interfaces">接口类型</param>
        /// <returns>返回继承了指定接口的接口</returns>
        public static Type[] GetSubInterface(string assemblyPath, params Type[] interfaces)
        {
            Assembly assembly = Assembly.Load(assemblyPath);
            return GetSubInterface(assembly, interfaces);
        }

        /// <summary>
        /// 获取程序集中继承了指定接口的接口
        /// </summary>
        /// <param name="types">类型集合</param>
        /// <param name="interfaces">接口类型</param>
        /// <returns>返回继承了指定接口的接口</returns>
        public static Type[] GetSubInterface(IEnumerable<Type> types, params Type[] interfaces)
        {
            return types.Where(type => ValidInterface(type, interfaces)).ToArray();
        }

        /// <summary>
        /// 获取程序集中实现了指定接口的类
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <param name="containAbstract">是否包含抽象类</param>
        /// <param name="interfaces">接口类型</param>
        /// <returns>返回实现了指定接口的类</returns>
        public static Type[] GetInterfaceSubClass(Assembly assembly, bool containAbstract,
            params Type[] interfaces)
        {
            return GetInterfaceSubClass(assembly.GetTypes(), containAbstract, interfaces);
        }

        /// <summary>
        /// 获取程序集中实现了指定接口的类
        /// </summary>
        /// <param name="assemblyPath">程序集路径</param>
        /// <param name="containAbstract">是否包含抽象类</param>
        /// <param name="interfaces">接口类型</param>
        /// <returns>返回实现了指定接口的类</returns>
        public static Type[] GetInterfaceSubClass(string assemblyPath, bool containAbstract,
            params Type[] interfaces)
        {
            Assembly assembly = Assembly.Load(assemblyPath);
            return GetInterfaceSubClass(assembly, containAbstract, interfaces);
        }

        /// <summary>
        /// 获取程序集中实现了指定接口的类
        /// </summary>
        /// <param name="types">程序集</param>
        /// <param name="containAbstract">是否包含抽象类</param>
        /// <param name="interfaces">接口类型</param>
        /// <returns>返回实现了指定接口的类</returns>
        public static Type[] GetInterfaceSubClass(IEnumerable<Type> types, bool containAbstract,
            params Type[] interfaces)
        {
            return types.Where(type => ValidInterfaceClass(type, containAbstract, interfaces)).ToArray();
        }

        /// <summary>
        /// 获取程序集中继承了指定类型的类或者实现了指定的接口(搜索整个继承继承链)。
        /// </summary>
        /// <param name="types">类型集合</param>
        /// <param name="containAbstract">是否包含抽象类</param>
        /// <param name="containInterface">是否包含接口</param>
        /// <param name="baseTypes">基类型</param>
        /// <returns>返回当前应用程序中的所有类型中检索继承自指定类型或者实现了指定类型的类型列表。</returns>
        public static Type[] GetSubClass(IEnumerable<Type> types, bool containAbstract, bool containInterface,
            Type[] baseTypes)
        {
            if (baseTypes == null || baseTypes.Length == 0) return null;
            var list = new List<Type>();
            foreach (Type t in types)
            {
                if (!containAbstract && t.IsAbstract)
                {
                    continue;
                }
                if (!containInterface && t.IsInterface)
                {
                    continue;
                }
                if (CheckSubClass(t, baseTypes))
                {
                    list.Add(t);
                }
            }
            return list.ToArray();
        }

        public static bool CheckSubClass(Type type, Type[] checkTypes)
        {
            if (type.BaseType != null)
            {
                if (checkTypes.Any(p => type.BaseType == p))
                {
                    return true;
                }
                return CheckSubClass(type.BaseType, checkTypes);
            }
            return false;
        }

        /// <summary>
        /// 检测type是否是baseType的子类(搜索整个继承链)
        /// </summary>
        /// <param name="type">检查的类型</param>
        /// <param name="baseTypes">基类</param>
        /// <returns>如果type是否是baseType的子类,返回true</returns>
        public static bool IsSubClass(Type type, Type[] baseTypes)
        {
            return CheckSubClass(type, baseTypes);
        }

        /// <summary>
        /// 验证接口是否继承自指定的接口(继承任意一个接口即可)
        /// </summary>
        /// <param name="type">待验证的接口类型</param>
        /// <param name="interfaces">接口类型</param>
        /// <returns>如果继承自指定的接口返回true</returns>
        public static bool ValidInterface(Type type, params Type[] interfaces)
        {
            return type.IsInterface && interfaces.Any(p => type.GetInterface(p.FullName) != null);
        }

        /// <summary>
        /// 验证类是否实现指定的接口(继承任意一个接口即可)
        /// </summary>
        /// <param name="type">待验证的类型</param>
        /// <param name="containAbstract">是否包含抽象类</param>
        /// <param name="interfaces">接口类型</param>
        /// <returns>如果类实现指定的接口返回true</returns>
        public static bool ValidInterfaceClass(Type type, bool containAbstract, params Type[] interfaces)
        {
            if (!type.IsClass || !type.IsPublic // || type.ContainsGenericParameters
                || (!containAbstract && type.IsAbstract))
            {
                return false;
            }

            return interfaces.Any(p => type.GetInterface(p.FullName) != null);
        }

        /// <summary>
        /// 验证类是否实现指定的接口(继承任意一个接口即可)
        /// </summary>
        /// <param name="type">待验证的类型</param>
        /// <param name="containAbstract">是否包含抽象类</param>
        /// <param name="classes">接口类型</param>
        /// <returns>如果类实现指定的接口返回true</returns>
        public static bool ValidClass(Type type, bool containAbstract, params Type[] classes)
        {
            if (!type.IsClass || !type.IsPublic // || type.ContainsGenericParameters
                || (!containAbstract && type.IsAbstract))
            {
                return false;
            }
            return classes.Any(p => type.BaseType == p.BaseType);
        }

        /// <summary>
        /// 获取类型全名包含程序集名称
        /// </summary>
        /// <param name="type">类型</param>
        public static string GetTypeFullName(Type type)
        {
            if (type.AssemblyQualifiedName != null)
            {
                string[] qualisz = type.AssemblyQualifiedName.Split(',');
                return String.Concat(qualisz[0], ",", qualisz[1]);
            }
            return String.Empty;
        }

        /// <summary>
        /// 获取程序集中指定名称的Icon资源
        /// </summary>
        /// <param name="name">Icon资源名称</param>
        /// <param name="assembly">程序集</param>
        /// <returns>返回Icon对象,如果不存在指定的资源名称则返回null</returns>
        public static Icon GetIconFromResources(string name, Assembly assembly)
        {
            Stream stream = assembly.GetManifestResourceStream(name);
            return stream == null ? null : new Icon(stream);
        }

        /// <summary>
        ///  获取程序集中指定名称的Image资源
        /// </summary>
        /// <param name="name">Image资源名称</param>
        /// <param name="assembly">程序集</param>
        /// <returns>返回Image对象,如果不存在指定的资源名称则返回null</returns>
        public static Image GetImageFromResources(string name, Assembly assembly)
        {
            Stream stream = assembly.GetManifestResourceStream(name);
            return stream == null ? null : Image.FromStream(stream);
        }

        /// <summary>
        /// 获取程序集中指定名称的文本资源
        /// </summary>
        /// <param name="name">资源名称</param>
        /// <param name="assembly">程序集</param>
        /// <returns>返回Text,如果不存在指定的资源名称则返回空字符串</returns>
        public static string GetTextFromResources(string name, Assembly assembly)
        {
            Stream stream = assembly.GetManifestResourceStream(name);
            return stream == null ? string.Empty : new StreamReader(stream).ReadToEnd();
        }

        /// <summary>
        /// 获取类自定义特性对象(如果有多个返回第一个,如果一个也没有返回null)
        /// </summary>
        /// <typeparam name="T">自定义特性类型</typeparam>
        /// <param name="type">对象类型</param>
        /// <param name="inherit">是否继承</param>
        public static T GetAttribute<T>(Type type, bool inherit = false) where T : Attribute
        {
            object[] attsz = type.GetCustomAttributes(typeof(T), inherit);
            if (attsz.Length > 0)
            {
                return attsz[0] as T;
            }
            return default(T);
        }

        /// <summary>
        /// 获取属性自定义特性对象(如果有多个返回第一个,如果一个也没有返回null)
        /// </summary>
        /// <typeparam name="T">自定义特性类型</typeparam>
        /// <param name="info">对象类型</param>
        /// <param name="inherit">是否继承</param>
        public static T GetAttribute<T>(PropertyInfo info, bool inherit = false) where T : Attribute
        {
            object[] attsz = info.GetCustomAttributes(typeof(T), inherit);
            if (attsz.Length > 0)
            {
                return attsz[0] as T;
            }
            return default(T);
        }

        /// <summary>
        /// 获取字段自定义特性对象(如果有多个返回第一个,如果一个也没有返回null)
        /// </summary>
        /// <typeparam name="T">自定义特性类型</typeparam>
        /// <param name="info">对象类型</param>
        /// <param name="inherit">是否继承</param>
        public static T GetAttribute<T>(FieldInfo info, bool inherit = false) where T : Attribute
        {
            object[] attsz = info.GetCustomAttributes(typeof(T), inherit);
            if (attsz.Length > 0)
            {
                T att = (T)attsz[0];
                if (att != null)
                {
                    return att;
                }
            }
            return default(T);
        }

        /// <summary>
        /// 获取程序集标题(AssemblyInfo.cs文件中AssemblyTitle属性定义的标题)
        /// </summary>
        public static string GetAssemblyTitle()
        {
            object[] attributes = Assembly.GetExecutingAssembly()
                .GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
            if (attributes.Length > 0)
            {
                var titleAttribute = (AssemblyTitleAttribute)attributes[0];
                if (titleAttribute.Title != "")
                {
                    return titleAttribute.Title;
                }
            }
            return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
        }


        /// <summary>
        /// 加载指定目录中的程序集
        /// </summary>
        /// <param name="dirs">目录列表</param>
        public static Type[] LoadType(IEnumerable<string> dirs)
        {
            var fileList = new List<string>();
            foreach (string p in dirs)
            {
                if (Directory.Exists(p) && !LoadedFileList.Any(x => IOHelper.EqualsDirectory(x, p)))
                {
                    fileList.AddRange(Directory.GetFiles(p));
                    LoadedFileList.Add(p);
                }
            }
            var typeList = new List<Type>();
            typeList.AddRange(LoadTypeByFile(fileList.ToArray()));
            return typeList.ToArray();
        }

        /// <summary>
        /// 加载指定文件中的程序集
        /// </summary>
        /// <param name="files">文件列表</param>
        public static Type[] LoadTypeByFile(string[] files)
        {
            var typeList = new List<Type>();
            foreach (string item in files)
            {
                if (!ValidateFileExtension(item)) continue;
                string assemblyName = Path.GetFileNameWithoutExtension(item);
                if (string.IsNullOrEmpty(assemblyName)) continue;
                try
                {
                    Assembly assembly = Assembly.Load(assemblyName);
                    foreach (var t in assembly.GetTypes())
                    {
                        if (typeList.IndexOf(t) == -1)
                        {
                            typeList.Add(t);
                        }
                    }
                }
                catch (Exception e)
                {
                    DebugHelper.DebugConsole(e.Message);
                }
            }

            return typeList.ToArray();
        }

        /// <summary>
        /// 验证文件扩展名
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>如果文件扩展是exe或者dll返回True</returns>
        private static bool ValidateFileExtension(string filePath)
        {
            string fileExtension = Path.GetExtension(filePath);
            if (string.IsNullOrEmpty(fileExtension)) return false;

            bool result = (fileExtension.Equals(".dll") || fileExtension.Equals(".exe"))
                          && filePath.IndexOf("vshost", StringComparison.Ordinal) == -1;
            return result;
        }

        /// <summary>
        /// 是否能成功加载指定的程序集
        /// </summary>
        /// <param name="assemblyFullNames">程序集全名数组</param>
        public static BoolResult IsCanLoadAssembly(string[] assemblyFullNames)
        {
            try
            {
                foreach (var item in assemblyFullNames)
                {
                    AppDomain.CurrentDomain.Load(item);
                }
                return BoolResult.True;
            }
            catch (Exception e)
            {
                return new BoolResult(false, e.Message);
            }
        }
    }
}